using System;
using System.Threading;
using System.Threading.Tasks;
using UnityEngine;

namespace Voodoo.Meta
{
	public class LeaderboardLayout : MonoBehaviour
	{
		[SerializeField]
		private RectTransform _slotParent;

		[SerializeField]
		private LeaderboardData _leaderboardData;

		[SerializeField]
		public LeaderboardRankData _leaderboardRankData;

		[SerializeField]
		private LeaderboardAnimationData _leaderboardAnimationData;

		private LeaderboardAnalytics _analytics;

		private CancellationTokenSource _animationCancelSource;

		private LeaderboardLayoutAnimation _layoutAnimation;

		private LeaderboardLayoutUI _layoutUI;

		private LeaderboardPlayerInfo _playerInfo;

		private LeaderboardRankLogic _rankLogic;

		public RectTransform SlotParent => _slotParent;

		public LeaderboardData LeaderboardData => _leaderboardData;

		public bool IsAnimating { get; private set; }

		public event Action<int> rankProgressionProcessed;

		public event Action rankUpdated;

		private void Awake()
		{
			_rankLogic = new LeaderboardRankLogic(_leaderboardRankData);
			_layoutUI = new LeaderboardLayoutUI(this, _rankLogic);
			_layoutAnimation = new LeaderboardLayoutAnimation(_layoutUI, _leaderboardAnimationData, _leaderboardData.spacing);
			_analytics = new LeaderboardAnalytics(_rankLogic);
			_layoutAnimation.rankUpdated += OnRankUpdated;
			_layoutAnimation.rankProgressionProcessed += OnRankProgressionProcessed;
		}

		private void OnDestroy()
		{
			_layoutAnimation.rankUpdated -= OnRankUpdated;
			_layoutAnimation.rankProgressionProcessed -= OnRankProgressionProcessed;
		}

		public void SetPlayerInfo(string playerName, Sprite playerFlag)
		{
			_playerInfo = new LeaderboardPlayerInfo(playerName, playerFlag);
		}

		public int GetPlayerRank()
		{
			return _rankLogic.GetPlayerRank();
		}

		public int GetNextRank(int previousScore, int newScore)
		{
			return _rankLogic.GetNextRank(previousScore, newScore);
		}

		public int GetNextRankFromStep(int previousScore, int newScore, int rankStep)
		{
			return _rankLogic.GetNextRankFromStep(previousScore, newScore, rankStep);
		}

		public int GetRankEarned(int newScore)
		{
			return _rankLogic.GetRankEarned(newScore);
		}

		public void Initialize(int previousScore, int newScore)
		{
			_rankLogic.Initialize(previousScore, newScore);
			_layoutUI.Fill(_playerInfo);
		}

		public async Task ShowAsync()
		{
			_analytics.SendShowLeaderboardEvent();
			try
			{
				IsAnimating = true;
				_animationCancelSource = new CancellationTokenSource();
				await _layoutAnimation.LaunchAnimationAsync(_animationCancelSource.Token);
			}
			catch (OperationCanceledException)
			{
			}
			finally
			{
				_rankLogic.SaveNewRank();
				IsAnimating = false;
			}
		}

		public void Hide()
		{
			_animationCancelSource.Cancel();
			_analytics.SendHideLeaderboardEvent();
			_layoutUI.Clear();
		}

		private void OnRankProgressionProcessed(int rank)
		{
			this.rankProgressionProcessed?.Invoke(rank);
		}

		private void OnRankUpdated()
		{
			this.rankUpdated?.Invoke();
		}
	}
}
